package sd.settemmezzo.player.thread;

import org.apache.log4j.Logger;

import sd.settemmezzo.common.Player;
import sd.settemmezzo.graphic.UI_Client;
import sd.settemmezzo.graphic.UI_Client.Mossa;
import sd.settemmezzo.player.state.GlobalState;
import sd.settemmezzo.player.state.LocalState;
import sd.settemmezzo.util.Message;
import sd.settemmezzo.util.Util;

public class WaitForInput extends Thread {
	private static Logger log = Logger.getLogger("WaitForInput");
	
	private LocalState	lstate;
	private GlobalState gstate;
	private UI_Client 	ui;
	private SendThreadFactory threads;
	
	public WaitForInput(GlobalState gs) {
		this.gstate = gs;
		this.lstate = LocalState.getInstance();
		this.ui = UI_Client.getInstance(lstate.getName());
		this.threads = new SendThreadFactory();
	}
	
	@Override
	public synchronized void run() {
		
		Message m;
		gstate.notifyChanged(ui);
		
		/* Attendo per una azione dell'utente */
		Mossa mossa = ui.waitForPlay(gstate);
		
		/* Aggiorno il gstate con la mossa ricevuta */
		gstate.setPuntata(lstate.getId(), mossa.puntata);
		gstate.setPunteggio(lstate.getId(), Util.calcolaPunteggio(gstate.getCarte(lstate.getId())));
		
		/* Se sono il mazziere */
		if (lstate.getId() == gstate.getMazziere().getId()) {
			lstate.setRuolo("leader");
		}
		
		gstate.notifyChanged(ui);
		
		/* Se sono il mazziere && non è più il mio turno, 
		 * vuol dire che è finito un giro di gioco */
		if (gstate.getMazziere().getId() == lstate.getId() && gstate.getToken() != lstate.getId()) {
			
			/* Do il tempo al di vedere l'ultima mano prima di resettare i tavoli */
			try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }
			
			/*  */
			fineMano();
			
			m = new Message(Message.FINE_MANO, gstate);
			
		} else {
			
			/* Inoltro lo stato condiviso */
			log.info("[setGlobalState] Invio gstate a: " + gstate.getRing().getNext(lstate.getId()).getNamePlayer());
			m = new Message(Message.GS_UPDATE, gstate);
		}
		
		threads.startSendThread(m, gstate.getRing().getNext(lstate.getId()));
		
	}

	private synchronized void fineMano() {
		int pId;
		int mId = lstate.getId();
		String msg = "";
		String eliminati = "";
		Player nuovoMazziere = null;
		
		/* Calcolo le vincite ed assegno i soldi */
		
		/* Prima il mazziere riscuote... */
		for (Player p : gstate.getRing()) {
			if (p.getId() != gstate.getMazziere().getId() 
					&& gstate.getSoldi(p.getId()) > 0
					&& Util.doesMazziereWin(gstate, p.getId())) {
				
				pId = p.getId();
				
				/* se il mazziere vince con un settemmezzo reale */
				if (gstate.getPunteggio(mId) == 7.6f && gstate.getPunteggio(pId) < 7.6f) {
					Util.pay(gstate.getPuntata(pId) * 2, pId, mId, gstate);
					msg += " - " + p.getNamePlayer() + " con " + gstate.getPunteggio(pId) + " punti perde " + gstate.getPuntata(pId) * 2 + " €\n";
				}
				/* se il mazziere vince, anche nel caso entrambi abbiano settemmezzo reali */
				else if (Util.doesMazziereWin(gstate, pId)) {
					Util.pay(gstate.getPuntata(pId), pId, mId, gstate);
					msg += " - " + p.getNamePlayer() + " con " + gstate.getPunteggio(pId) + " punti perde " + gstate.getPuntata(pId) + " €\n";
				}
				
				/* Vedo se qualcuno è stato eliminato */
				if (gstate.getSoldi(p.getId()) == 0) {
					eliminati += "\n - " + p.getNamePlayer() + " è stato eliminato";
					if (p.getId() == gstate.getMazziere().getId() && nuovoMazziere == null)
						nuovoMazziere = gstate.getRing().getNext(p);
				}
			}
		}
		
		/* ...poi paga i giocatori */
		for (Player p : gstate.getRing()) {
			if (p.getId() != gstate.getMazziere().getId() 
					&& gstate.getSoldi(p.getId()) > 0
					&& !Util.doesMazziereWin(gstate, p.getId())) {
				
				pId = p.getId();
				
				/* se il player vince con un settemmezzo reale */
				if (gstate.getPunteggio(pId) == 7.6f && !Util.doesMazziereWin(gstate, pId)) {
					Util.pay(gstate.getPuntata(pId) * 2, mId, pId, gstate);
					msg += " - " + p.getNamePlayer() + " con 7.5 Reale vince " + gstate.getPuntata(pId) * 2 + " €\n";
					
					nuovoMazziere = p;
				
				/* se il mazziere perde */
				} else {
					Util.pay(gstate.getPuntata(pId), mId, pId, gstate);
					msg += " - " + p.getNamePlayer() + " con " + gstate.getPunteggio(pId) + " punti vince " + gstate.getPuntata(pId) + " €\n";
				}
			}
		}
		
		msg += eliminati;
		
		if (nuovoMazziere != null) {
			gstate.setMazziere(nuovoMazziere);
			//gstate.getRing().configMazziere(nuovoMazziere.getId());
			gstate.configMazziere(nuovoMazziere.getId());
			lstate.setRuolo("normal");
			//gstate.setToken(Util.findNextPlayer(nuovoMazziere, gstate.getPlayersList()).getId());
			gstate.setToken(gstate.getRing().getNext(nuovoMazziere).getId());
			msg += "\n\nIl nuovo mazziere è: " + nuovoMazziere.getNamePlayer();
			msg += "\nAmmontare del banco: " + gstate.getSoldi(nuovoMazziere.getId()) + " €";
		} else {
			msg += "\n\nAmmontare del banco: " + gstate.getSoldi(gstate.getMazziere().getId()) + " €";
		}
		
		//gstate.setMessage(new Messaggio(Messaggio.GS_UPDATE, msg));
		gstate.setMessage(msg);		
		
		log.info("[setGlobalState] Sono mazziere, creo carte!");
		// Se non ci sono almeno tante carte quanti giocatori, resetto il mazzo
		if (gstate.getDeck().size() < gstate.countActivePlayers()) {
			gstate.resetDeck();
			fineMazzo();
		}
		Util.carteCoperte(gstate);
		gstate.notifyChanged(ui);
	}
	
	/* Quando finisce il mazzo il mazziere diventa il successivo del mazziere 
	 * e il turno viene dato al successivo del nuovo mazziere */
	private void fineMazzo() {
		Player nuovoMazziere = gstate.getRing().getNext(gstate.getMazziere());
		
		while (gstate.getSoldi(nuovoMazziere.getId()) <= 0) {
			nuovoMazziere = gstate.getRing().getNext(nuovoMazziere);
		}
		
		gstate.setMazziere(nuovoMazziere);
		gstate.configMazziere(nuovoMazziere.getId());
		gstate.setToken(gstate.getRing().getNext(nuovoMazziere).getId());
		
		lstate.setRuolo("normal");
	}
}
